#[derive(RustcDecodable)]
struct Options {
- flag_package: Option<String>,
+ flag_package: Vec<String>,
flag_target: Option<String>,
flag_manifest_path: Option<String>,
flag_verbose: bool,
cargo clean [options]
Options:
- -h, --help Print this message
- -p SPEC, --package SPEC Package to clean artifacts for
- --manifest-path PATH Path to the manifest to the package to clean
- --target TRIPLE Target triple to clean output for (default all)
- -v, --verbose Use verbose output
- -q, --quiet No output printed to stdout
- --color WHEN Coloring: auto, always, never
+ -h, --help Print this message
+ -p SPEC, --package SPEC ... Package to clean artifacts for
+ --manifest-path PATH Path to the manifest to the package to clean
+ --target TRIPLE Target triple to clean output for (default all)
+ -v, --verbose Use verbose output
+ -q, --quiet No output printed to stdout
+ --color WHEN Coloring: auto, always, never
If the --package argument is given, then SPEC is a package id specification
which indicates which package's artifacts should be cleaned out. If it is not
let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
let opts = ops::CleanOptions {
config: config,
- spec: options.flag_package.as_ref().map(|s| &s[..]),
+ spec: &options.flag_package,
target: options.flag_target.as_ref().map(|s| &s[..]),
};
ops::clean(&root, &opts).map(|_| None).map_err(|err| {
use ops::{self, Layout, Context, BuildConfig, Kind};
pub struct CleanOptions<'a> {
- pub spec: Option<&'a str>,
+ pub spec: &'a [String],
pub target: Option<&'a str>,
pub config: &'a Config,
}
// If we have a spec, then we need to delete some packages, otherwise, just
// remove the whole target directory and be done with it!
- let spec = match opts.spec {
- Some(spec) => spec,
- None => return rm_rf(&target_dir),
- };
+ if opts.spec.len() == 0 {
+ return rm_rf(&target_dir);
+ }
- // Load the lockfile (if one's available), and resolve spec to a pkgid
+ // Load the lockfile (if one's available)
let lockfile = root.root().join("Cargo.lock");
let source_id = root.package_id().source_id();
let resolve = match try!(ops::load_lockfile(&lockfile, source_id)) {
Some(resolve) => resolve,
None => return Err(human("A Cargo.lock must exist before cleaning"))
};
- let pkgid = try!(resolve.query(spec));
-
- // Translate the PackageId to a Package
- let pkg = {
- let mut source = pkgid.source_id().load(opts.config);
- try!(source.update());
- (try!(source.get(&[pkgid.clone()]))).into_iter().next().unwrap()
- };
- // Create a compilation context to have access to information like target
+ // Create a compilation context to have access to information like target
// filenames and such
let srcs = SourceMap::new();
let pkgs = PackageSet::new(&[]);
None, BuildConfig::default(),
&profiles));
- // And finally, clean everything out!
- for target in pkg.targets().iter() {
- // TODO: `cargo clean --release`
- let layout = Layout::new(opts.config, &root, opts.target, "debug");
- try!(rm_rf(&layout.fingerprint(&pkg)));
- let profiles = [Profile::default_dev(), Profile::default_test()];
- for profile in profiles.iter() {
- for filename in try!(cx.target_filenames(&pkg, target, profile,
- Kind::Target)).iter() {
- try!(rm_rf(&layout.dest().join(&filename)));
- try!(rm_rf(&layout.deps().join(&filename)));
+ // resolve package specs and remove the corresponding packages
+ for spec in opts.spec {
+ let pkgid = try!(resolve.query(spec));
+
+ // Translate the PackageId to a Package
+ let pkg = {
+ let mut source = pkgid.source_id().load(opts.config);
+ try!(source.update());
+ (try!(source.get(&[pkgid.clone()]))).into_iter().next().unwrap()
+ };
+
+ // And finally, clean everything out!
+ for target in pkg.targets().iter() {
+ // TODO: `cargo clean --release`
+ let layout = Layout::new(opts.config, &root, opts.target, "debug");
+ try!(rm_rf(&layout.fingerprint(&pkg)));
+ let profiles = [Profile::default_dev(), Profile::default_test()];
+ for profile in profiles.iter() {
+ for filename in try!(cx.target_filenames(&pkg, target, profile,
+ Kind::Target)).iter() {
+ try!(rm_rf(&layout.dest().join(&filename)));
+ try!(rm_rf(&layout.deps().join(&filename)));
+ }
}
}
}
use support::{project, execs, main_file, basic_bin_manifest};
-use hamcrest::{assert_that, existing_dir, is_not};
+use hamcrest::{assert_that, existing_dir, existing_file, is_not};
fn setup() {
}
execs().with_status(0).with_stdout(""));
assert_that(&p.build_dir(), is_not(existing_dir()));
});
+
+test!(clean_multiple_packages {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies.d1]
+ path = "d1"
+ [dependencies.d2]
+ path = "d2"
+
+ [[bin]]
+ name = "foo"
+ "#)
+ .file("src/foo.rs", &main_file(r#""i am foo""#, &[]))
+ .file("d1/Cargo.toml", r#"
+ [package]
+ name = "d1"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d1"
+ "#)
+ .file("d1/src/main.rs", "fn main() { println!(\"d1\"); }")
+ .file("d2/Cargo.toml", r#"
+ [package]
+ name = "d2"
+ version = "0.0.1"
+ authors = []
+
+ [[bin]]
+ name = "d2"
+ "#)
+ .file("d2/src/main.rs", "fn main() { println!(\"d2\"); }");
+ p.build();
+
+ assert_that(p.cargo_process("build").arg("-p").arg("d1").arg("-p").arg("d2")
+ .arg("-p").arg("foo"),
+ execs().with_status(0));
+
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.build_dir().join("debug").join("deps").join("d1"), existing_file());
+ assert_that(&p.build_dir().join("debug").join("deps").join("d2"), existing_file());
+
+ assert_that(p.cargo("clean").arg("-p").arg("d1").arg("-p").arg("d2")
+ .cwd(&p.root().join("src")),
+ execs().with_status(0).with_stdout(""));
+ assert_that(&p.bin("foo"), existing_file());
+ assert_that(&p.build_dir().join("debug").join("deps").join("d1"),
+ is_not(existing_file()));
+ assert_that(&p.build_dir().join("debug").join("deps").join("d2"),
+ is_not(existing_file()));
+});